﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Services;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using System.Xml.Linq;
using LoadGenerator;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.Table;

namespace LoadController
{
    public partial class _Overview : Page
    {
        private static CloudTable ActiveJob = null;
        private static CloudTable FinishedJobs = null;
        private static CloudTable Queue = null;

        public Job objActiveJob = null;
        private Result currentResult = null;

        private static CloudBlobContainer resultContainer;

        //public string GetCheckMark(object finished)
        //{
        //    bool hasFinished = (bool)finished;
        //    return hasFinished ? "icon-busy" : "icon-cancel-2";
        //}
        
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1));
            Response.Cache.SetCacheability(HttpCacheability.NoCache);
            Response.Cache.SetNoStore();
            Response.AppendHeader("pragma", "no-cache");

            if (!Page.IsPostBack)
            {
                Queue = AzureTableHelper.GetCloudTable(AppSettings.Table_Queue);
                FinishedJobs = AzureTableHelper.GetCloudTable(AppSettings.Table_FinishedJobs);
                ActiveJob = AzureTableHelper.GetCloudTable(AppSettings.Table_ActiveJob);
                resultContainer = AzureBlobHelper.GetContainerReference(AppSettings.BlobContainer_results);

                //GridViewActiveJob.Visible = false;

                FillGridViewQueue();
                FillGridViewFinishedJobs();
                CheckActiveJob();
            }
        }

        protected void ActiveJob_Tick(object sender, EventArgs e)
        {
            CheckActiveJob();
        }


        private void CheckActiveJob()
        {
            TimerActiveJob.Enabled = false;

            List<Job> lst = AzureTableHelper.RetrieveAllEntities<Job>(ActiveJob).ToList();
            objActiveJob = lst.FirstOrDefault();

            if (objActiveJob == null)
            {
                //handle controls
                ActiveJobIsEmpty.Visible = true;
                Panel1.Visible = false;
                GridViewActiveJob.Visible = false;
                UpdatePanelActiveJobGridView.Update();
            }

            if (objActiveJob != null)
            {
                ActiveJobIsEmpty.Visible = false;

                if (AzureBlobHelper.CheckBlobExists(resultContainer, objActiveJob.originalPK))
                {
                    var byteArr = AzureBlobHelper.DownloadBlobToByteArray(resultContainer, objActiveJob.originalPK);
                    currentResult = ResultSerializer.Deserialize(byteArr);
                }

                if (!GridViewActiveJob.Visible)
                {
                    List<Job> newlst = new List<Job>();
                    newlst.Add(objActiveJob);

                    GridViewActiveJob.DataSource = newlst;
                    GridViewActiveJob.DataBind();
                    GridViewActiveJob.HeaderRow.TableSection = TableRowSection.TableHeader;

                    GridViewActiveJob.Visible = true;
                    UpdatePanelActiveJobGridView.Update();

                    FillGridViewQueue();
                    UpdatePanelQueue.Update();
                }

                if (currentResult != null)
                {
                    if (currentResult.JobFinished)
                    {
                        currentResult = null;
                        progressValue.InnerText = "0%";
                        progressbarLeft.Style.Add("width", "0%");
                        progressbarRight.Style.Add("width", "100%");

                        TimerFinishedJobs.Enabled = false;
                        FillGridViewFinishedJobs();
                        UpdatePanelFinishedJobs.Update();
                        TimerFinishedJobs.Enabled = true;

                        GridViewActiveJob.Visible = false;
                        UpdatePanelActiveJobGridView.Update();

                        objActiveJob = null;
                    }
                    else
                    {
                        ActiveJobIsEmpty.Visible = false;
                        GridViewActiveJob.Visible = true;
                        Panel1.Visible = true;

                        progressbarLeft.Style.Add("width", currentResult.Progress.ToString() + "%");
                        progressbarRight.Style.Add("width", (100 - currentResult.Progress).ToString() + "%");
                        progressValue.InnerText = currentResult.Progress.ToString() + "%" + " | " + currentResult.RemainingTime;
                    }

                    if (objActiveJob != null && lst.FirstOrDefault() != null)
                    {
                        if (!objActiveJob.PartitionKey.Equals(lst.FirstOrDefault().PartitionKey))
                        {
                            //List<Job> newlst = new List<Job>();
                            //newlst.Add(objActiveJob);

                            //GridViewActiveJob.DataSource = newlst;
                            //GridViewActiveJob.DataBind();
                            //GridViewActiveJob.HeaderRow.TableSection = TableRowSection.TableHeader;

                            //GridViewActiveJob.Visible = true;
                            //UpdatePanelActiveJobGridView.Update();

                            FillGridViewQueue();
                            UpdatePanelQueue.Update();
                        }
                    }

                    if (lst.Count == 0)
                    {
                        ActiveJobIsEmpty.Visible = true;
                        Panel1.Visible = false;

                        GridViewActiveJob.Visible = false;
                        UpdatePanelActiveJobGridView.Update();
                    }


                }
                else
                {
                    Panel1.Visible = true;
                    progressbarLeft.Style.Add("width", "0%");
                    progressbarRight.Style.Add("width", "100%");
                    progressValue.InnerText = "0%" + " | " + "00:00:00";
                }
            }

            TimerActiveJob.Enabled = true;

        }

        private void FillGridViewActiveJob()
        {
            TimerActiveJob.Enabled = false;

            List<Job> lst = AzureTableHelper.RetrieveAllEntities<Job>(ActiveJob).ToList();

            if (currentResult != null)
            {
                if (currentResult.JobFinished)
                {
                    TimerFinishedJobs.Enabled = false;
                    FillGridViewFinishedJobs();
                    UpdatePanelFinishedJobs.Update();
                    TimerFinishedJobs.Enabled = true;

                    GridViewActiveJob.Visible = false;
                    UpdatePanelActiveJobGridView.Update();
                }
            }

            if (objActiveJob == null)
            {
                GridViewActiveJob.Visible = false;
                UpdatePanelActiveJobGridView.Update();
            }

            if (objActiveJob != null)
            {
                if (AzureBlobHelper.CheckBlobExists(resultContainer, objActiveJob.originalPK))
                {
                    var byteArr = AzureBlobHelper.DownloadBlobToByteArray(resultContainer, objActiveJob.originalPK);
                    currentResult = ResultSerializer.Deserialize(byteArr);
                }
            }

            if (objActiveJob != null && lst.FirstOrDefault() != null)
            {
                if (!objActiveJob.PartitionKey.Equals(lst.FirstOrDefault()))
                {
                    objActiveJob = lst.FirstOrDefault();
                    lst.Clear();
                    lst.Add(objActiveJob);

                    GridViewActiveJob.DataSource = lst;
                    GridViewActiveJob.DataBind();
                    GridViewActiveJob.HeaderRow.TableSection = TableRowSection.TableHeader;

                    GridViewActiveJob.Visible = true;
                    UpdatePanelActiveJobGridView.Update();
                }
            }

            if (lst.Count == 0)
            {
                ActiveJobIsEmpty.Visible = true;
                Panel1.Visible = false;
            }
            else
            {
                GridViewActiveJob.Visible = true;
                Panel1.Visible = true;

                objActiveJob = lst.FirstOrDefault();
                lst.Clear();
                lst.Add(objActiveJob);

                GridViewActiveJob.DataSource = lst;
                GridViewActiveJob.DataBind();
                GridViewActiveJob.HeaderRow.TableSection = TableRowSection.TableHeader;

                if (AzureBlobHelper.CheckBlobExists(resultContainer, objActiveJob.originalPK))
                {
                    var byteArr = AzureBlobHelper.DownloadBlobToByteArray(resultContainer, objActiveJob.originalPK);
                    currentResult = ResultSerializer.Deserialize(byteArr);
                
                    progressbarLeft.Style.Add("width", currentResult.Progress.ToString() + "%");
                    progressbarRight.Style.Add("width", (100-currentResult.Progress).ToString() + "%");
                    progressValue.InnerText = currentResult.Progress.ToString() + "%" + " | " + currentResult.RemainingTime;
                }
                else
                {
                    currentResult = null;
                    progressValue.InnerText = "0%";
                    progressbarLeft.Style.Add("width", "0%");
                    progressbarRight.Style.Add("width", "100%");
                }
            }

            TimerActiveJob.Enabled = true;
        }

        private void FillGridViewQueue()
        {
            TimerQueue.Enabled = false;

            List<Job> lst = AzureTableHelper.RetrieveAllEntities<Job>(Queue).Reverse<Job>().ToList();

            if (lst.Count == 0)
            {
                QueueIsEmpty.Visible = true;
                GridViewQueue.Visible = false;
            }
            else
            {
                QueueIsEmpty.Visible = false;
                GridViewQueue.Visible = true;

                GridViewQueue.DataSource = lst;
                GridViewQueue.DataBind();
                GridViewQueue.HeaderRow.TableSection = TableRowSection.TableHeader;
            }

            TimerQueue.Enabled = true;
        }

        protected void Queue_Tick(object sender, EventArgs e)
        {
            FillGridViewQueue();
        }

        protected void GridViewQueue_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            TimerQueue.Enabled = false;

            GridViewQueue.DataSource = AzureTableHelper.RetrieveAllEntities<Job>(Queue).ToList();

            GridViewQueue.PageIndex = e.NewPageIndex;
            GridViewQueue.DataBind();
            GridViewQueue.HeaderRow.TableSection = TableRowSection.TableHeader;

            TimerQueue.Enabled = true;
        }

        private void FillGridViewFinishedJobs()
        {
            TimerFinishedJobs.Enabled = false;

            List<Job> lst = AzureTableHelper.RetrieveAllEntities<Job>(FinishedJobs).ToList();
            
            if (lst.Count == 0)
            {
                FinishedJobsIsEmpty.Visible = true;
                GridViewFinishedJobs.Visible = false;
            }
            else
            {
                FinishedJobsIsEmpty.Visible = false;
                GridViewFinishedJobs.Visible = true;

                GridViewFinishedJobs.DataSource = lst;
                GridViewFinishedJobs.DataBind();
                GridViewFinishedJobs.HeaderRow.TableSection = TableRowSection.TableHeader;
            }

            TimerFinishedJobs.Enabled = true;
        }

        protected void FinishedJobs_Tick(object sender, EventArgs e)
        {
            FillGridViewFinishedJobs();
        }

        protected void GridViewFinishedJobs_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            TimerFinishedJobs.Enabled = false;

            GridViewFinishedJobs.DataSource = AzureTableHelper.RetrieveAllEntities<Job>(FinishedJobs).ToList();

            GridViewFinishedJobs.PageIndex = e.NewPageIndex;
            GridViewFinishedJobs.DataBind();
            GridViewFinishedJobs.HeaderRow.TableSection = TableRowSection.TableHeader;

            TimerFinishedJobs.Enabled = true;
        }

        protected void GridViewFinishedJobs_RowCreated(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.Pager)
            {
                SetPagerButtonStates(GridViewFinishedJobs, e.Row, this);
            }
        }

        public static void SetPagerButtonStates(System.Web.UI.WebControls.GridView gridView, GridViewRow gvPagerRow, Page page)
        {

            int pageIndex = gridView.PageIndex;
            int pageCount = gridView.PageCount;
            LinkButton btnFirst = (LinkButton)gvPagerRow.FindControl("Previous");
            LinkButton btnPrevious = (LinkButton)gvPagerRow.FindControl("Button2");
            LinkButton btnNext = (LinkButton)gvPagerRow.FindControl("Button3");
            LinkButton btnLast = (LinkButton)gvPagerRow.FindControl("Button4");
            //Label label = (Label)gvPagerRow.FindControl("Label1");
            //label.Text = (pageIndex + 1) + "/" + pageCount;
            btnFirst.Enabled = btnPrevious.Enabled = (pageIndex != 0);
            btnNext.Enabled = btnLast.Enabled = (pageIndex < (pageCount - 1));
            //DropDownList ddlPageSelector = (DropDownList)gvPagerRow.FindControl("ddl");
            LinkButton lb;
            int startIndex = (pageIndex / 4) * 4;
            int temp;
            for (int i = 1; i < 5; i++)
            {
                lb = (LinkButton)gvPagerRow.FindControl("linkbutton" + i);
                temp = startIndex + i;
                if (temp <= pageCount)
                {

                    lb.Text = temp.ToString();

                    lb.CommandArgument = temp.ToString();
                    if (temp == pageIndex + 1)
                        lb.ForeColor = System.Drawing.Color.Red;
                }
                else
                    lb.Visible = false;
            }

            lb = (LinkButton)gvPagerRow.FindControl("linkbutton5");
            if (startIndex + 4 >= pageCount)
                lb.Visible = false;
            lb.Click += delegate
            {
                gridView.PageIndex += 4;
            };

            lb = (LinkButton)gvPagerRow.FindControl("linkbutton6");
            if (startIndex - 4 < 0)
                lb.Visible = false;
            lb.Click += delegate
            {
                gridView.PageIndex -= 4;
            };

            //ddlPageSelector.Items.Clear();
            //for (int i = 1; i <= gridView.PageCount; i++)
            //{
            //    ddlPageSelector.Items.Add(i.ToString());
            //}
            //ddlPageSelector.SelectedIndex = pageIndex;
            //ddlPageSelector.SelectedIndexChanged += delegate
            //{
            //    gridView.PageIndex = ddlPageSelector.SelectedIndex;
            //    gridView.DataBind();
            //};
        }

        [WebMethod]
        public static void AbortActiveJob()
        {
            LoadGenerator.RoleCommunicator.AbortActiveJob();
        }

        [WebMethod]
        public static void DeleteJob(string jobid)
        {
            TableQuery<Job> jobFinishedQuery = new TableQuery<Job>().Where(
                    TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, jobid));

            CloudTable ct = AzureTableHelper.GetCloudTable(AppSettings.Table_FinishedJobs);
            Job JobToDelete = ct.ExecuteQuery<Job>(jobFinishedQuery).SingleOrDefault();

            if (JobToDelete != null)
            {
                AzureTableHelper.DeleteEntity(ct,JobToDelete);
                AzureBlobHelper.DeleteBlob(AppSettings.BlobContainer_results, jobid);
            }
        }

        [WebMethod]
        public static void DeleteJobInQueue(string jobid)
        {
            TableQuery<Job> jobQuery = new TableQuery<Job>().Where(
                    TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, jobid));

            CloudTable ct = AzureTableHelper.GetCloudTable(AppSettings.Table_Queue);
            Job JobToDelete = ct.ExecuteQuery<Job>(jobQuery).SingleOrDefault();

            if (JobToDelete != null)
            {
                AzureTableHelper.DeleteEntity(ct, JobToDelete);
            }
        }
    }
}